package cn.isjinhao.se.structure;

import java.util.Iterator;

/**
 * @Author ISJINHAO
 * @Date 2021/7/1 23:11
 */
public interface RetrieveSupported<K, E extends KeySupported<K>> extends Iterable<E> {

    int size();

    E get(int index);

    E remove(int index, boolean moveData);

    default E remove(int index) {
        return remove(index, true);
    }

    default E remove(K key) {
        return remove(key, true);
    }

    default E remove(K key, boolean moveData) {
        int indexNo = getIndexNo(key);
        if (indexNo != -1) {
            return remove(indexNo, moveData);
        }
        return null;
    }

    boolean set(int index, E e, boolean moveData);

    default boolean set(int index, E e) {
        return set(index, e, false);
    }

    default boolean set(K key, E e) {
        return set(key, e, false);
    }

    default boolean set(K key, E e, boolean moveData) {
        int indexNo = getIndexNo(key);
        if (indexNo != -1) {
            return set(indexNo, e, moveData);
        }
        return false;
    }

    default E get(K key) {
        int indexNo = getIndexNo(key);
        if (indexNo != -1) {
            return get(indexNo);
        }
        return null;
    }

    default boolean append(E e) {
        return set(size(), e);
    }

    default int getIndexNo(K key) {
        if (key == null) {
            return -1;
        }
        int i = 0;
        for (E e : this) {
            if (key.equals(e.key())) {
                return i;
            }
            i++;
        }
        return -1;
    }

    default boolean contains(K key) {
        int indexNo = getIndexNo(key);
        return indexNo != -1;
    }

    default boolean checkIndexInRange(int index) {
        return index >= 0 && index < size();
    }

    default boolean checkIndexCanAdd(int index) {
        return index >= 0 && index <= size();
    }

    @Override
    default Iterator<E> iterator() {
        return new RetrieveSupportedIterator<K, E>(this) {
        };
    }

    abstract class RetrieveSupportedIterator<K, E extends KeySupported<K>> implements Iterator<E> {

        private int cursor = 0;

        private final RetrieveSupported<K, E> retrieveSupported;

        public RetrieveSupportedIterator(RetrieveSupported<K, E> retrieveSupported) {
            this.retrieveSupported = retrieveSupported;
        }

        @Override
        public boolean hasNext() {
            return cursor < retrieveSupported.size();
        }

        @Override
        public E next() {
            E e = retrieveSupported.get(cursor);
            cursor++;
            return e;
        }
    }

}
